from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator, ValidationError

MPPA = (('JP-18+', 'JP-18+'), ('PG-13', 'PG-13'))
TAG_TYPE = (
    (1, '主题'), (2, '系列'), (3, '角色'), (4, '服裝'), (5, '體型'), (6, '行為'), (7, '玩法'), (8, '類別'), (9, '其他'),
    (10, '清晰度'), (11, '自定义'),
)
ROLE_CHOICES = ((1, '导演'), (2, '主角'), (3, '配角'), (4, '联合出演'))


class Film(models.Model):
    # 标识信息
    num = models.CharField(
        max_length=64, verbose_name='影片代号', db_index=True, unique=True
    )
    title = models.CharField(max_length=256, verbose_name='标题')
    sort_title = models.CharField(
        max_length=256, verbose_name='排序标题', help_text='用于排序的标题（可能包含编号前缀）', blank=True, null=True
    )
    original_title = models.CharField(
        max_length=256, verbose_name='源标题', blank=True, null=True
    )
    # 剧情描述
    plot = models.TextField(verbose_name='剧情简介', blank=True, null=True)
    outline = models.TextField(verbose_name='剧情概要', blank=True, null=True)
    original_plot = models.TextField(verbose_name='原始剧情', blank=True, null=True)
    tagline = models.CharField(max_length=512, verbose_name='宣传语', blank=True, null=True)

    # 发行日期相关
    premiered = models.DateField(verbose_name='首映日期', blank=True, null=True)
    release_date = models.DateField(verbose_name='发行日期', blank=True, null=True)
    year = models.PositiveSmallIntegerField(
        verbose_name='发行年份',
        validators=[MinValueValidator(1900), MaxValueValidator(2100)],
        blank=True, null=True
    )

    # 分级与地区
    mpaa = models.CharField(
        max_length=16, verbose_name='分级', choices=MPPA, default='JP-18+'
    )
    countrycode = models.OneToOneField(
        'actors.Country', max_length=16, verbose_name='国家地区', on_delete=models.SET_NULL, blank=True, null=True
    )

    # 媒体信息
    cover_url = models.URLField(verbose_name='封面URL', blank=True, null=True)
    trailer_url = models.URLField(verbose_name='预告片URL', blank=True, null=True)
    website_url = models.URLField(verbose_name='官网URL', blank=True, null=True)

    # 统计信息
    runtime = models.PositiveIntegerField(
        verbose_name='时长(分钟)',
        help_text='影片时长(分钟)',
        blank=True, null=True
    )
    rating = models.FloatField(
        verbose_name='用户评分',
        validators=[MinValueValidator(0.0), MaxValueValidator(5.0)],
        blank=True, null=True
    )
    critic_rating = models.IntegerField(
        verbose_name='专业评分',
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        blank=True, null=True
    )
    votes = models.PositiveIntegerField(verbose_name='评分人数', default=0)
    is_hot = models.BooleanField(
        verbose_name='是否热门',
        default=False,
        help_text='系统自动标记的热门影片'
    )

    # 马赛克
    mosaic = models.BooleanField(verbose_name='是否有码', default=True)

    # 关系字段
    tags = models.ManyToManyField('FilmTag', verbose_name='标签', related_name='film_tags')

    create_time = models.DateTimeField(auto_now=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now_add=True, verbose_name='更新时间')

    class Meta:
        db_table = 'cin_film'
        verbose_name = '影片信息'
        verbose_name_plural = verbose_name
        indexes = [
            models.Index(fields=['votes']),
            models.Index(fields=['year', 'rating']),
            models.Index(fields=['premiered', 'is_hot']),
        ]

    def __str__(self):
        return f'{self.num} - {self.title}'

    def poster(self):
        """获取类型为1的主海报"""
        poster = self.film_to_poster.filter(type=2).first()
        if poster.poster and poster.poster.name:
            return poster.poster.url

    def get_background_poster(self):
        """获取类型为1的主海报"""
        return self.film_to_poster.filter(type=1).first()

    def get_stage_poster(self):
        """获取剧照"""
        return self.film_to_poster.filter(type=5).order_by('poster').all()

    def get_rating_stars(self):
        full_stars = int(self.rating / 2)
        return '★' * full_stars + '☆' * (5 - full_stars)


class ActorToFilm(models.Model):
    actor = models.ForeignKey(
        'actors.Actor',
        on_delete=models.CASCADE,
        related_name='film_roles',
    )
    film = models.ForeignKey(
        Film, on_delete=models.CASCADE,
        related_name='cast'
    )
    role = models.PositiveSmallIntegerField(
        verbose_name='角色',
        choices=ROLE_CHOICES,
        default=1,
        validators=[MinValueValidator(1), MaxValueValidator(4)]
    )
    is_representative = models.BooleanField(verbose_name='代表作', default=False)

    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'film_to_actor'
        verbose_name = '演职员关系'
        verbose_name_plural = verbose_name
        unique_together = [('actor', 'film', 'role')]  # 联合索引

    def __str__(self):
        return f"{self.actor.name} - {self.film.title} - {self.get_role_display()}"


class FilmTag(models.Model):
    value = models.CharField(max_length=64, verbose_name='标签')
    tag_type = models.PositiveSmallIntegerField(
        verbose_name='标签类型',
        choices=TAG_TYPE,
        default=1,
        validators=[MinValueValidator(1), MaxValueValidator(11)]
    )

    class Meta:
        db_table = 'cin_film_tag'
        verbose_name = '影片标签'
        verbose_name_plural = verbose_name
        unique_together = [('value', 'tag_type')]

    def __str__(self):
        return self.value


def poster_save_path(instance: 'FilmToPoster', filename):
    """剧照存放目录"""
    if instance.type == 5:
        return f"poster/{instance.film.num}/stagePhoto/{filename}"
    return f"poster/{instance.film.num}/{filename}"


class FilmToPoster(models.Model):
    PHOTO_TYPE = (
        (1, 'fanarts-背景图'),
        (2, 'poster-海报图'),
        (3, 'thumb-缩略图'),
        (5, '剧照'),
    )

    film = models.ForeignKey(
        Film, on_delete=models.CASCADE,
        related_name='film_to_poster'
    )
    poster = models.ImageField(
        upload_to=poster_save_path,
        unique=True,
    )
    type = models.IntegerField(
        verbose_name='图片类型',
        choices=PHOTO_TYPE
    )

    class Meta:
        db_table = 'cin_film_poster'
        verbose_name = '影片剧照关联表'
        verbose_name_plural = verbose_name


class FilmToCompany(models.Model):
    film = models.ForeignKey(
        Film,
        related_name='company_to_film',
        verbose_name='影片',
        on_delete=models.CASCADE,

    )
    studio = models.ForeignKey(
        'actors.Company',
        related_name='studio_films',
        verbose_name='制作公司',
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    publisher = models.ForeignKey(
        'actors.Company',
        verbose_name='供应商',
        related_name='supplier_films',
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )

    class Meta:
        db_table = 'cin_film_to_company'
        verbose_name = '影片公司关联表'
        verbose_name_plural = verbose_name
        # 移除 constraints 中的条件约束（因为 MySQL 不支持）
        constraints = [
            models.UniqueConstraint(
                fields=['film', 'studio'],
                name='unique_film_studio',
                condition=models.Q(studio__isnull=False)
            ),
            models.UniqueConstraint(
                fields=['film', 'publisher'],
                name='unique_film_publisher',
                condition=models.Q(publisher__isnull=False)
            )
        ]

    def clean(self):
        """
        模型级别验证 - 确保条件唯一约束
        """
        super().clean()

        # 使用Q对象合并查询
        conflict_filters = models.Q()
        if self.studio:
            conflict_filters |= models.Q(film=self.film, studio=self.studio)
        if self.publisher:
            conflict_filters |= models.Q(film=self.film, publisher=self.publisher)

        if conflict_filters:
            conflicts = FilmToCompany.objects.filter(
                conflict_filters
            ).exclude(pk=self.pk)

            if conflicts.exists():
                raise ValidationError(
                    '同一影片不能有重复的制作公司或供应商'
                )

    def save(self, *args, **kwargs):
        """
        保存前执行完整验证
        """
        self.full_clean()
        super().save(*args, **kwargs)
